14. 矩阵函数
矩阵函数
Matrix 类的最后一部分涉及到矩阵函数的实现。你需要尽可能多地练习矩阵运算编程,包括加法、乘法、转置、求逆等。
我们建议,你至少需要实现一个矩阵加法,以及一个名为 matrix_print 的函数,它使用 cout 将矩阵输出到终端。在本页最后给出的参考答案中,我们还提供了matrix_transpose 函数的代码。
实现这些类的函数与实现本课前面的 get 和 set 函数是一样的。你将需要在 matrix.h 中声明函数,并在 matrix.cpp 中定义函数。一般语法也是一样的:
类函数声明语法
return datatype functionname(datatype for variable1,
datatype for variable2, ..., datatype for variablen)
类函数定义语法
return datatype Classname::functionname(datatype variable1,
datatype variable2, ..., datatype variablen) {
code defining the function;
}
编写矩阵函数
在本练习中,你将声明并定义将两个矩阵相加的矩阵类函数。以下是矩阵加法函数的输入和输出:
输入:
- 一个矩阵,它将被添加到 grid 变量中
输出:
- 包含 grid 变量矩阵和输入矩阵之和的一个矩阵
由于 matrix_addition 函数的输入是矩阵,因此需要使用 Matrix 类作为数据类型来声明并定义函数。这似乎有点混乱,但和本课前面介绍的 Gaussian 类中的 mul 和 add 函数完全相同。你可以使用这些作为编写 matrix_addition 函数的指南。
以下是 gaussian.h 中的 mul 和 add 函数的函数声明,供参考:
Gaussian mul (Gaussian);
Gaussian add (Gaussian);
这两个函数都接收高斯值并输出高斯值。以下是 gaussian.cpp 的函数定义:
Gaussian Gaussian::mul(Gaussian other) {
float denominator;
float numerator;
float new_mu;
float new_var;
denominator = sigma2 + other.getSigma2();
numerator = mu * other.getSigma2() + other.getMu() * sigma2;
new_mu = numerator / denominator;
new_var = 1.0 / ( (1.0 / sigma2) + (1.0 / other.sigma2) );
return Gaussian(new_mu, new_var);
}
Gaussian Gaussian::add(Gaussian other) {
float new_mu;
float new_sigma2;
new_mu = mu + other.getMu();
new_sigma2 = sigma2 + other.getSigma2();
return Gaussian(new_mu, new_sigma2);
}
虽然 matrix_addition 函数的实现有所不同,但一般结构与 Gaussian 示例中的 mul 和 add 函数相同。
你还需要编写一个 matrix_print 函数,该函数使用 cout 向终端输出一个矩阵。matrix_print 函数没有输入,也没有输出。
在 matrix.cpp 和 matrix.h 代码中填充 TODO 部分。
Start Quiz:
#include <iostream>
#include <vector>
#include "matrix.h"
int main () {
// TODO: Nothing to do here
return 0;
}
#include "matrix.h"
Matrix::Matrix() {
std::vector <std:: vector <float> > initial_grid (10, std::vector <float>(5, 0.5));
grid = initial_grid;
rows = initial_grid.size();
cols = initial_grid[0].size();
}
Matrix::Matrix(std::vector <std:: vector <float> > initial_grid) {
grid = initial_grid;
rows = initial_grid.size();
cols = initial_grid[0].size();
}
void Matrix::setGrid(std::vector< std::vector<float> > new_grid) {
grid = new_grid;
rows = new_grid.size();
cols = new_grid[0].size();
}
std::vector< std::vector<float> > Matrix::getGrid() {
return grid;
}
std::vector<int>::size_type Matrix::getRows() {
return rows;
}
std::vector<int>::size_type Matrix::getCols() {
return cols;
}
/* TODO: Define a matrix_addition function
** INPUT: a matrix
** OUPUT: the sum of the grid variable and the input matrix
**
** STEPS:
** 1. check that the matrix in the grid variable
** and the input matrix have the same size
**
** if not, throw an error like
** throw std::invalid_argument("matrices are not the same size");
**
** 2. add the matrices together and return
** the result as a Matrix. You can do this part
** with nested for loops. If you use an intermediate
** vector to store a row, the vector.clear()
** method might be useful.
**
*/
/* TODO: Define a matrix_print function
** This function has no inputs and no outputs
** The purpose of the function is to display the matrix in
** the terminal using std::cout.
**
**
** The output should look something like:
** 4 9 1 10
** 5 11 6 17
** 8 4 15 2
*/
#include <vector>
#include <stdexcept> //library for the invalid_argument method
#include <iostream>
class Matrix
{
private:
std::vector< std::vector<float> > grid;
std::vector<float>::size_type rows;
std::vector<float>::size_type cols;
public:
// constructor functions
Matrix ();
Matrix (std::vector< std::vector<float> >);
// set functions
void setGrid(std::vector< std::vector<float> >);
// get functions
std::vector< std::vector<float> > getGrid();
std::vector<float>::size_type getRows();
std::vector<float>::size_type getCols();
/* TODO: Declare the matrix_addition function
** INPUTS: a Matrix
** OUTPUTS: a Matrix
**
** TODO: Declare the matrix_print function
** INPUTS: none
** OUTPUTS: none
*/
};
matrix.h 参考答案
# include <vector>
# include <iostream>
# include <stdexcept>
# include <vector>
class Matrix
{
private:
std::vector< std::vector<float> > grid;
std::vector<int>::size_type rows;
std::vector<int>::size_type cols;
public:
// 构造函数
Matrix ();
Matrix (std::vector< std::vector<float> >);
// set 函数
void setGrid(std::vector< std::vector<float> >);
// get 函数
std::vector< std::vector<float> > getGrid();
std::vector<int>::size_type getRows();
std::vector<int>::size_type getCols();
// 矩阵函数
Matrix matrix_transpose();
Matrix matrix_addition(Matrix);
//矩阵打印
void matrix_print();
};
matrix.cpp 参考答案
# include "matrix.h"
Matrix::Matrix() {
std::vector <std:: vector <float> > initial_grid (10, std::vector <float>(5, 0.5));
grid = initial_grid;
rows = initial_grid.size();
cols = initial_grid[0].size();
}
Matrix::Matrix(std::vector <std:: vector <float> > initial_grid) {
grid = initial_grid;
rows = initial_grid.size();
cols = initial_grid[0].size();
}
void Matrix::setGrid(std::vector< std::vector<float> > new_grid) {
grid = new_grid;
rows = new_grid.size();
cols = new_grid[0].size();
}
std::vector< std::vector<float> > Matrix::getGrid() {
return grid;
}
std::vector<int>::size_type Matrix::getRows() {
return rows;
}
std::vector<int>::size_type Matrix::getCols() {
return cols;
}
Matrix Matrix::matrix_transpose() {
std::vector< std::vector<float> > new_grid;
std::vector<float> row;
for (int i = 0; i < cols; i++) {
row.clear();
for (int j = 0; j < rows; j++) {
row.push_back(grid[j][i]);
}
new_grid.push_back(row);
}
return Matrix(new_grid);
}
Matrix Matrix::matrix_addition(Matrix other) {
if ((rows != other.getRows()) || (cols != other.getCols())) {
throw std::invalid_argument( "matrices are not the same size" );
}
std::vector< std::vector<float> > othergrid = other.getGrid();
std::vector< std::vector<float> > result;
std::vector<float> new_row;
for (int i = 0; i < rows; i++) {
new_row.clear();
for (int j = 0; j < cols; j++) {
new_row.push_back(grid[i][j] + othergrid[i][j]);
}
result.push_back(new_row);
}
return Matrix(result);
}
void Matrix::matrix_print() {
std::cout << std::endl;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
std::cout << grid[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}